package es.xpt.ysf.model;

import java.util.Calendar;
import java.util.Date;

public final class IntervalUtils {

	/**
	 * Obtiene un periodo que concatena este periodo y el indicado
	 * en el argumento del procedimeinto.
	 * La concatenacion tiene lugar siempre que exista interseccion, o
	 * que las fechas sean consecutivas.
	 * Para dos periodos [fA-fB] y [f1-f2], tal que fA < f1,
	 * si existe interseccion entre ambos, o se cumple que f1 = fB + 1 dia,
	 * entonces el resultado es [fA - f2].
	 * En otro caso devuelve null.
	 * @param pA
	 * @param pB
	 * @return
	 */
	public static Interval append(Interval pA, Interval pB ) {
		long pAf1 = pA.f1;
		long pAf2 = pA.f2;
		long pBf1 = pB.f1;
		long pBf2 = pB.f2;
		
		if( Math.max(pAf1, pBf1) > Math.min(pAf2, pBf2) ) {
			if( pAf2 < pBf1 ) {
				Calendar c = Calendar.getInstance();
				c.setTimeInMillis(pAf2);
				c.add(pA.getPeriodUnitsType().getCalendarType(), pA.getPeriodUnits());
				if( c.getTimeInMillis() < pBf1 )
					return null;
			}
			else if( pBf2 < pAf1 ) {
				Calendar c = Calendar.getInstance();
				c.setTimeInMillis(pBf2);
				c.add(pA.getPeriodUnitsType().getCalendarType(), pA.getPeriodUnits());
				if( c.getTimeInMillis() < pAf1 )
					return null;
			}
		}
		pAf1 = Math.min(pAf1, pBf1);
		pAf2 = Math.max(pAf2, pBf2);
		return new Interval(new Date(pAf1), new Date(pAf2), pA.getPeriodUnits(), pA.getPeriodUnitsType());
	}


	/**
	 * Obtiene un periodo resultado de la interseccion de este periodo
	 * y el indicado en el argumento del procedimiento.
	 * Si no existe interseccion, se devuelve null.
	 * Para dos periodos [fA-fB] y [f1-f2], existe interseccion si se cuple
	 * que fA <= f2 y f1 <= fB.
	 * @param pA
	 * @param pB
	 * @return Periodo de interseccion.
	 */
	public static Interval join(Interval pA, Interval pB) {
		long l1 = Math.max(pA.f1, pB.f1);
		long l2 = Math.min(pA.f2, pB.f2);
		if( l1 <= l2 ) {
			return new Interval(new Date(l1), new Date(l2), pA.getPeriodUnits(), pA.getPeriodUnitsType());
		} 
		return null;
	}

	/**
	 * @param pA
	 * @param pB
	 * @return
	 */
	public static boolean existJoin(Interval pA, Interval pB) {
		return pA.f1 <= pB.f2 &&  pB.f1 <= pA.f2;
	}
	/**
	 * @param pA
	 * @param pB
	 * @return
	 */
//	public static boolean existJoin(MultiInterval pA, Interval pB) {
//		return pA.existJoin(pB);
//	}
	/**
	 * @param pA
	 * @param pB
	 * @return
	 */
//	public static boolean existJoin(Interval pA, MultiInterval pB) {
//		return pB.existJoin(pA);
//	}
	/**
	 * @param pA
	 * @param pB
	 * @return
	 */
//	public static boolean existJoin(MultiInterval pA, MultiInterval pB) {
//		return pA.existJoin(pB);
//	}

}
